﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YJKSparseDistance.Properties;
using YJKGeometryFuncs;
using YJKGeometryFuncs.CurveUtility;
using YJKInspectModelFunc;
using YJKInspectModelFunc.ModelLayer;

namespace YJKSparseDistance.ModelLayer
{
	public class ObstructurePacker_EvacuationDistance : BaseHostInRoomPacker
	{
		public ObstructurePacker_EvacuationDistance(Element inputElement, RevitLinkInstance useRevitLinkInstance = null, object[] otherValues = null) : base(inputElement, useRevitLinkInstance, otherValues)
		{
			if (base.ThisElement.Category.Id.IntegerValue == -2000120 && inputElement is Stairs)
			{
				this.m_bIfStairs = true;
			}
			BoundingBoxXYZ boundingBoxXYZ = base.ThisElement.get_BoundingBox(null);
			this.m_thisBoundingBox = boundingBoxXYZ;
			if (boundingBoxXYZ != null && base.UseTransform != null)
			{
				this.m_thisBoundingBox = new BoundingBoxXYZ();
				this.m_thisBoundingBox.Max = Geometry.TransformPoint(boundingBoxXYZ.Max, base.UseTransform);
				this.m_thisBoundingBox.Min = Geometry.TransformPoint(boundingBoxXYZ.Min, base.UseTransform);
			}
		}

		public bool IfStairs
		{
			get
			{
				return this.m_bIfStairs;
			}
		}

		public BoundingBoxXYZ ThisBoundingBox
		{
			get
			{
				return this.m_thisBoundingBox;
			}
		}

		public List<Curve> GetBoundingBoxCurveAtZ(double input)
		{
			if (base.ThisElement is Opening)
			{
				return this.GetOpengingCurve(input);
			}
			if (this.ThisBoundingBox == null)
			{
				return null;
			}
			if (base.ThisElement is Railing)
			{
				bool hasHost = (base.ThisElement as Railing).HasHost;
				return this.GetRalilngCurve(input);
			}
			return null;
		}

		private List<Curve> GetStairsCurve(double input)
		{
			StairsRun anearestStairsRun = Utility.GetANearestStairsRun(base.ThisElement as Stairs, input, base.UseTransform);
			if (anearestStairsRun == null)
			{
				return null;
			}
			List<Curve> list = new List<Curve>();
			Curve curve = anearestStairsRun.GetStairsPath().ElementAt(0);
			XYZ endPoint = curve.GetEndPoint(0);
			curve = this.GetAFitCurve(input, curve);
			foreach (Curve pathCurve in anearestStairsRun.GetFootprintBoundary())
			{
				Curve afitCurve = this.GetAFitCurve(input, pathCurve);
				double num;
				if (!Utility.IfPointOnCurve(afitCurve, endPoint, out num))
				{
					list.Add(afitCurve);
				}
			}
			return list;
		}

		private Curve GetAFitCurve(double input, Curve pathCurve)
		{
			if (base.UseTransform != null)
			{
				pathCurve = pathCurve.CreateTransformed(base.UseTransform);
			}
            pathCurve = YJKInspectModelFunc.Utility.TransformCurveAtZAixs(pathCurve, input, true);
			return pathCurve;
		}

		private List<Curve> GetOpengingCurve(double input)
		{
			List<Curve> list = new List<Curve>();
			foreach (object obj in (base.ThisElement as Opening).BoundaryCurves)
			{
				Curve curve = (Curve)obj;
				Curve curve2 = curve.Clone();
                curve2 = YJKInspectModelFunc.Utility.TransformCurveAtZAixs(curve, input, true);
				if (base.UseRevitLinkInstance != null)
				{
					list.Add(curve2.CreateTransformed(base.UseTransform));
				}
				else
				{
					list.Add(curve2);
				}
			}
			return list;
		}

		private List<Curve> GetBoundingBoxCurve(double input)
		{
			XYZ xyz = this.ThisBoundingBox.Max;
			xyz = new XYZ(xyz.X, xyz.Y, input);
			XYZ xyz2 = this.ThisBoundingBox.Min;
			xyz2 = new XYZ(xyz2.X, xyz2.Y, input);
			return new List<Curve>
			{
				Line.CreateBound(new XYZ(xyz2.X, xyz.Y, input), xyz),
				Line.CreateBound(xyz, new XYZ(xyz.X, xyz2.Y, input)),
				Line.CreateBound(new XYZ(xyz.X, xyz2.Y, input), xyz2),
				Line.CreateBound(xyz2, new XYZ(xyz2.X, xyz.Y, input))
			};
		}

		private List<Curve> GetRalilngCurve(double input)
		{
			List<Curve> list = new List<Curve>();
			double num = double.Parse(Resources.Str_OffestValueForRailing);
			num = AssistFunc.mmToFeet(num) / 2.0;
			num += double.Parse(Resources.Str_OffestValue);
			int num2 = 0;
			foreach (Curve curve in (base.ThisElement as Railing).GetPath())
			{
				Curve curve2 = curve.Clone();
				if (base.UseTransform != null)
				{
					curve2 = curve2.CreateTransformed(base.UseTransform);
				}
                curve2 = YJKInspectModelFunc.Utility.TransformCurveAtZAixs(curve2, input, true);
				Curve curve3 = curve2.Clone();
				curve3.MakeUnbound();
				double num3 = curve2.GetEndParameter(0) - num / curve2.Length * (curve2.GetEndParameter(1) - curve2.GetEndParameter(0));
				double num4 = curve2.GetEndParameter(1) + num / curve2.Length * (curve2.GetEndParameter(1) - curve2.GetEndParameter(0));
				curve3.MakeBound(num3, num4);
				list.Add(curve2);
				list.Add(CurveUtility.CreateOffsetCurve(curve3, num));
				list.Add(CurveUtility.CreateOffsetCurve(curve3, -num));
				list.AddRange(Utility.MakeEndCurves(list[num2 + 1], list[num2 + 2]));
				num2 += 5;
			}
			return list;
		}

		private bool m_bIfStairs;

		private BoundingBoxXYZ m_thisBoundingBox;
	}
}
